﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using Kang.Monitor.Wpf.Service;
using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.Geo;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace Kang.Monitor.Wpf.Views
{
    internal class IndexViewModel : ObservableObject
    {
        private string _currTime;

        public string CurrTime
        {
            get { return _currTime; }
            set { SetProperty(ref _currTime, value); }
        }

        public HeatLandSeries[] MapSeries { get; set; }
        private readonly IWeigthedMapLand _brazil;
        private readonly Random _r = new();
        public ModbusHelp _modbusHelp { get; set; }

        public IndexViewModel(ModbusHelp modbusHelp)
        {
            _modbusHelp = modbusHelp;
            //解决汉字问题
            LiveCharts.Configure(config =>
            config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')));
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = new TimeSpan(0, 0, 0, 1);//一秒间隔
            timer.Tick += timer_Tick;
            timer.IsEnabled = true;//使能

            var lands = new HeatLand[]
       {
            new() { Name = "bra", Value = 13 },
            new() { Name = "mex", Value = 10 },
            new() { Name = "usa", Value = 15 },
            new() { Name = "can", Value = 8 },
            new() { Name = "ind", Value = 12 },
            new() { Name = "deu", Value = 13 },
            new() { Name= "jpn", Value = 15 },
            new() { Name = "chn", Value = 14 },
            new() { Name = "rus", Value = 11 },
            new() { Name = "fra", Value = 8 },
            new() { Name = "esp", Value = 7 },
            new() { Name = "kor", Value = 10 },
            new() { Name = "zaf", Value = 12 },
            new() { Name = "are", Value = 13 }
       };

            MapSeries = new HeatLandSeries[] { new HeatLandSeries { Lands = lands } };

            _brazil = lands.First(x => x.Name == "bra");
            DoRandomChanges();

            DoModbus();
        }

        private void timer_Tick(object? sender, EventArgs e)
        {
            CurrTime = DateTime.Now.ToString("yyyy-HH-dd HH:mm:ss");
        }

        #region 压力

        private static readonly SKColor s_blue = new(25, 118, 210);
        private static readonly SKColor s_red = new(229, 57, 53);
        private static readonly SKColor s_yellow = new(198, 167, 0);

        private static ObservableCollection<ObservableValue> _observableStressValues = new ObservableCollection<ObservableValue>();

        public ObservableCollection<ISeries> StressSeries { get; set; } = new ObservableCollection<ISeries>()
   {
        new LineSeries<ObservableValue>
        {
            Values =_observableStressValues,

             Fill = null,
             GeometrySize = 0,
             GeometryStroke=new SolidColorPaint(s_blue,1),
               Stroke=new SolidColorPaint(s_blue,1),
            LineSmoothness = 1, // mark
        }
    };

        public Axis[] StressXAxes { get; set; } =
  {
        new Axis
        {
            // Use the Label property to indicate the format of the labels in the axis
            // The Labeler takes the value of the label as parameter and must return it as string
            Labeler = (value) =>
               "",
        }
    };

        public Axis[] StressYAxes { get; set; } =
    {
        new Axis
        {
            LabelsPaint = new SolidColorPaint
            {
                Color = SKColors.White,
            },
            MinLimit = 0,
            MinStep =1,

            // Use the Labeler property to give format to the axis values // mark
            // Now the Y axis we will display it as currency
            // LiveCharts provides some common formatters
            // in this case we are using the currency formatter.
            // Labeler = Labelers.Currency // mark

            // you could also build your own currency formatter
            // for example:
              Labeler = (value) =>$"{value.ToString()}Pa"

            // But the one that LiveCharts provides creates shorter labels when
            // the amount is in millions or trillions
        }
    };

        #endregion 压力

        #region 温度

        private static ObservableCollection<ObservableValue> _observableTemperatureValues = new ObservableCollection<ObservableValue>();

        public ObservableCollection<ISeries> TemperatureSeries { get; set; } = new ObservableCollection<ISeries>()
   {
        new LineSeries<ObservableValue>
        {
            Values = _observableTemperatureValues,
             Fill = null,
             GeometrySize = 0,
            LineSmoothness = 1, // mark
               GeometryStroke=new SolidColorPaint(s_blue,1),
               Stroke=new SolidColorPaint(s_blue,1),
        }
    };

        public Axis[] TemperatureXAxes { get; set; } =
  {
        new Axis
        {
            // Use the Label property to indicate the format of the labels in the axis
            // The Labeler takes the value of the label as parameter and must return it as string
            Labeler = (value) =>
               "",
        }
    };

        public Axis[] TemperatureYAxes { get; set; } =
    {
        new Axis
        {
            LabelsPaint = new SolidColorPaint
            {
                Color = SKColors.White,
            },
            MinLimit = 0,
            MinStep =1,

            // Use the Labeler property to give format to the axis values // mark
            // Now the Y axis we will display it as currency
            // LiveCharts provides some common formatters
            // in this case we are using the currency formatter.
            // Labeler = Labelers.Currency // mark

            // you could also build your own currency formatter
            // for example:
              Labeler = (value) =>$"{value.ToString()}℃"

            // But the one that LiveCharts provides creates shorter labels when
            // the amount is in millions or trillions
        }
    };

        #endregion 温度

        #region 进口浓度

        private static ObservableCollection<ObservableValue> _observableEntryDensityValues = new ObservableCollection<ObservableValue>();

        public ObservableCollection<ISeries> EntryDensitySeries { get; set; } = new ObservableCollection<ISeries>()
   {
        new LineSeries<ObservableValue>
        {
            Values = _observableEntryDensityValues,
             Fill = null,
             GeometrySize = 0,
            LineSmoothness = 1, // mark
               GeometryStroke=new SolidColorPaint(s_blue,1),
               Stroke=new SolidColorPaint(s_blue,1),
        }
    };

        public Axis[] EntryDensityXAxes { get; set; } =
  {
        new Axis
        {
            // Use the Label property to indicate the format of the labels in the axis
            // The Labeler takes the value of the label as parameter and must return it as string
            Labeler = (value) =>
               "",
        }
    };

        public Axis[] EntryDensityYAxes { get; set; } =
    {
        new Axis
        {
            LabelsPaint = new SolidColorPaint
            {
                Color = SKColors.White,
            },
            MinLimit = 0,
            MinStep =1,

            // Use the Labeler property to give format to the axis values // mark
            // Now the Y axis we will display it as currency
            // LiveCharts provides some common formatters
            // in this case we are using the currency formatter.
            // Labeler = Labelers.Currency // mark

            // you could also build your own currency formatter
            // for example:
              Labeler = (value) =>$"{value.ToString()}mg/L"

            // But the one that LiveCharts provides creates shorter labels when
            // the amount is in millions or trillions
        }
    };

        #endregion 进口浓度

        #region 出口浓度

        private static ObservableCollection<ObservableValue> _observableExportDensityValues = new ObservableCollection<ObservableValue>();

        public ObservableCollection<ISeries> ExportDensitySeries { get; set; } = new ObservableCollection<ISeries>()
   {
        new LineSeries<ObservableValue>
        {
            Values = _observableExportDensityValues,
             Fill = null,
             GeometrySize = 0,
            LineSmoothness = 1, // mark
               GeometryStroke=new SolidColorPaint(s_blue,1),
               Stroke=new SolidColorPaint(s_blue,1),
        }
    };

        public Axis[] ExportDensityXAxes { get; set; } =
  {
        new Axis
        {
            // Use the Label property to indicate the format of the labels in the axis
            // The Labeler takes the value of the label as parameter and must return it as string
            Labeler = (value) =>
               "",
        }
    };

        public Axis[] ExportDensityYAxes { get; set; } =
    {
        new Axis
        {
            LabelsPaint = new SolidColorPaint
            {
                Color = SKColors.White,
            },
            MinLimit = 0,
            MinStep =1,

            // Use the Labeler property to give format to the axis values // mark
            // Now the Y axis we will display it as currency
            // LiveCharts provides some common formatters
            // in this case we are using the currency formatter.
            // Labeler = Labelers.Currency // mark

            // you could also build your own currency formatter
            // for example:
              Labeler = (value) =>$"{value.ToString()}mg/L"

            // But the one that LiveCharts provides creates shorter labels when
            // the amount is in millions or trillions
        }
    };

        #endregion 出口浓度

        private async void DoRandomChanges()
        {
            await Task.Delay(1000);

            while (true)
            {
                foreach (var shape in MapSeries[0].Lands ?? Enumerable.Empty<IWeigthedMapLand>())
                {
                    shape.Value = _r.Next(0, 20);
                }

                await Task.Delay(500);
            }
        }

        private void DoModbus()
        {
            //var modbusHelp = Ioc.Default.GetRequiredService<ModbusHelp>();
            _modbusHelp.DoModbus((values) =>
            {
                if (_observableStressValues.Count > 60)
                {
                    _observableStressValues.RemoveAt(0);
                }
                _observableStressValues.Add(new(values[0]));
                if (_observableTemperatureValues.Count > 60)
                {
                    _observableTemperatureValues.RemoveAt(0);
                }
                _observableTemperatureValues.Add(new(values[1]));

                if (_observableEntryDensityValues.Count > 60)
                {
                    _observableEntryDensityValues.RemoveAt(0);
                }
                _observableEntryDensityValues.Add(new(values[2]));

                if (_observableExportDensityValues.Count > 60)
                {
                    _observableExportDensityValues.RemoveAt(0);
                }
                _observableExportDensityValues.Add(new(values[3]));
            });
            //#region Modbus通信

            //Task.Run(async () =>
            //    {
            //        SerialPort serialPort = null;
            //        try
            //        {
            //            using (serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One))
            //            {
            //                serialPort.Open();
            //                while (true)
            //                {
            //                    await Task.Delay(500);
            //                    Modbus.Device.IModbusSerialMaster master = Modbus.Device.ModbusSerialMaster.CreateRtu(serialPort);

            //                    ushort[] values = master.ReadHoldingRegisters(1, 0, 4);
            //                    //for (int i = 0; i < 4; i++)
            //                    //{
            //                    //    // Evironment[i].Value = values[i];
            //                    //}
            //                    if (_observableStressValues.Count > 60)
            //                    {
            //                        _observableStressValues.RemoveAt(0);
            //                    }
            //                    _observableStressValues.Add(new(values[0]));
            //                    if (_observableTemperatureValues.Count > 60)
            //                    {
            //                        _observableTemperatureValues.RemoveAt(0);
            //                    }
            //                    _observableTemperatureValues.Add(new(values[1]));

            //                    if (_observableEntryDensityValues.Count > 60)
            //                    {
            //                        _observableEntryDensityValues.RemoveAt(0);
            //                    }
            //                    _observableEntryDensityValues.Add(new(values[2]));

            //                    if (_observableExportDensityValues.Count > 60)
            //                    {
            //                        _observableExportDensityValues.RemoveAt(0);
            //                    }
            //                    _observableExportDensityValues.Add(new(values[3]));
            //                }
            //            }
            //        }
            //        catch (Exception)
            //        {
            //        }
            //        finally
            //        {
            //            serialPort?.Close();
            //        }
            //    }
            //    );

            //#endregion Modbus通信
        }
    }
}